/*
 * @Author: Broin
 * @Date: 2021-11-12 13:54:23
 * @LastEditTime: 2022-01-12 10:38:18
 * @LastEditors: your name
 * @Description: 
 * @FilePath: /myCore/os/src/sbi.rs
 * MADE BY BROIN
 */


#![allow(unused)]

use core::arch::asm;

const SBI_SET_TIMER: usize = 0;
const SBI_CONSOLE_PUTCHAR: usize = 1;
const SBI_CONSOLE_GETCHAR: usize = 2;
const SBI_CLEAR_IPI: usize = 3;
const SBI_SEND_IPI: usize = 4;
const SBI_REMOTE_FENCE_I: usize = 5;
const SBI_REMOTE_SFENCE_VMA: usize = 6;
const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7;
const SBI_SHUTDOWN: usize = 8;


#[inline(always)]
fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
    let mut ret;
    unsafe {
        asm!(
            "ecall",
            inlateout("x10") arg0 => ret,
            in("x11") arg1,
            in("x12") arg2,
            in("x17") which,
        );
    }
    ret
}

/**
 * @description: SBI调用 
 * @param {*}
 * @return {*}
 */
// #[inline(always)]
// fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
//     let ret;
//     unsafe {
//         llvm_asm!("ecall"
//             : "={x10}" (ret)
//             : "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (which)
//             : "memory"      // TODO: （学习）在汇编可能改变内存的情况下，需要加入memory选项
//             : "volatile"   
//         );
//     }
//     ret
// }



/**
 * @description: 向控制台输出一个字符
 * @param {usize} c
 * @return {*}
 */
pub fn console_putchar(c: usize) {
    sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
}


/**
 * @description: 读取控制台的一个字符
 * @param {*}
 * @return {*} 读取到的字符，若没有读取到，则返回-1
 */
pub fn console_getchar() -> usize {
    sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0)
}

/**
 * @description: 关闭操作系统（退出QEMU）
 * @param {*}
 * @return {*}
 */
pub fn shutdown() -> ! {
    sbi_call(SBI_SHUTDOWN, 0, 0, 0);
    panic!("It should shutdown!");
}

